package com.naiterui.ehp.bs.ds.modules.order.service.impl;

import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.ExcelImportUtil;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import cn.afterturn.easypoi.excel.entity.ImportParams;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.base.Preconditions;
import com.naiterui.ehp.bp.bo.b2c.OrderDeliveryBO;
import com.naiterui.ehp.bp.security.utils.SecurityUtils;
import com.naiterui.ehp.bp.support.exception.BaseExceptionCodes;
import com.naiterui.ehp.bp.support.exception.BusinessException;
import com.naiterui.ehp.bs.ds.common.utils.BarCodeUtil;
import com.naiterui.ehp.bs.ds.common.utils.DateUtils;
import com.naiterui.ehp.bs.ds.common.utils.JwtUser;
import com.naiterui.ehp.bs.ds.common.utils.PageVO;
import com.naiterui.ehp.bs.ds.common.vo.PageParamsVO;
import com.naiterui.ehp.bs.ds.modules.order.entity.Order;
import com.naiterui.ehp.bs.ds.modules.order.entity.OrderUser;
import com.naiterui.ehp.bs.ds.modules.order.feign.IOrderFeignClient;
import com.naiterui.ehp.bs.ds.modules.order.mapper.OrderItemMapper;
import com.naiterui.ehp.bs.ds.modules.order.mapper.OrderMapper;
import com.naiterui.ehp.bs.ds.modules.order.mapper.OrderUserMapper;
import com.naiterui.ehp.bs.ds.modules.order.service.IOrderService;
import com.naiterui.ehp.bs.ds.modules.order.vo.DeliveryExcelVO;
import com.naiterui.ehp.bs.ds.modules.order.vo.LogisticsCompanyVO;
import com.naiterui.ehp.bs.ds.modules.order.vo.OrderDetailVO;
import com.naiterui.ehp.bs.ds.modules.order.vo.OrderExcelVO;
import com.naiterui.ehp.bs.ds.modules.order.vo.OrderItemVO;
import com.naiterui.ehp.bs.ds.modules.order.vo.OrderUserVO;
import com.naiterui.ehp.bs.ds.modules.order.vo.OrderVO;
import com.naiterui.ehp.bs.ds.modules.order.vo.PrintOrderDetailVO;
import com.naiterui.ehp.bs.ds.modules.order.vo.StatisticalVO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.time.temporal.ChronoUnit;
import java.util.Base64;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import javax.imageio.ImageIO;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

@Service
@RequiredArgsConstructor
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements IOrderService {

  private final OrderItemMapper orderItemMapper;
  private final OrderUserMapper orderUserMapper;
  private final IOrderFeignClient orderFeignClient;

  @Value("${ehp.domain.img}")
  private String imgDomain;

  @Override
  public PageVO<OrderVO> queryPage(PageParamsVO pageParamsVO, OrderVO orderVO) {
    QueryWrapper<OrderVO> entityWrapper = pageParamsVO.getEntityWrapper("t");
    JwtUser currentUser = SecurityUtils.getCurrentUser();
    Long warehouseId = currentUser.getWarehouseId();
    Preconditions.checkNotNull(warehouseId, "仓库ID不能为null");
    entityWrapper.eq("t.warehouse_id", warehouseId);

    String orderSn = orderVO.getOrderSn();
    if (StringUtils.isNotBlank(orderSn)) {
      entityWrapper.in("t.order_sn", orderSn.split("\n"));
    }
    String phone = orderVO.getPhone();
    entityWrapper.eq(StringUtils.isNotBlank(phone), "eou.phone", phone);

    String receiver = orderVO.getReceiver();
    entityWrapper.eq(StringUtils.isNotBlank(receiver), "eou.receiver", receiver);

    //发货日期
    String sendTimeGte = orderVO.getSendTimeGte();
    String sendTimeLte = orderVO.getSendTimeLte();
    entityWrapper.ge(StringUtils.isNotBlank(sendTimeGte), "t.send_time", sendTimeGte);
    entityWrapper.orderByDesc("created_at");
    if (StringUtils.isNotBlank(sendTimeLte)) {
      if (DateUtils.isNow(sendTimeLte)) {
        Date plus = DateUtils.plus(DateUtils.parseStrToDate(sendTimeLte), 1, ChronoUnit.DAYS);
        entityWrapper.le("t.send_time", plus);
      } else {
        entityWrapper.le("t.send_time", sendTimeLte);
      }
    }

    Integer orderStatus = orderVO.getOrderStatus();
    entityWrapper.eq(orderStatus != null, "t.order_status", orderStatus);
    //不能看到待审核订单
    entityWrapper.ne("t.order_status", 7);
    entityWrapper.ne("t.order_status", 8);

    //商品sku码
    String skuNumber = orderVO.getSkuNumber();
    entityWrapper.eq(StringUtils.isNotBlank(skuNumber), "ps.number", skuNumber);

    //商品名称
    String skuName = orderVO.getSkuName();
    entityWrapper.like(StringUtils.isNotBlank(skuName), "ps.name", skuName);

    Page<OrderVO> page = this.baseMapper.getPage(pageParamsVO.getPage(), entityWrapper);
    return PageVO.toPageVo(page);
  }

  @Override
  public StatisticalVO getStatisticalVO() {
    StatisticalVO statisticalVO = new StatisticalVO();

    //今天
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
    JwtUser currentUser = SecurityUtils.getCurrentUser();
    Long warehouseId = currentUser.getWarehouseId();
    Preconditions.checkNotNull(warehouseId, "仓库ID不能为null");

    Long toDayQuantity = this.baseMapper.getStatistical(warehouseId, sdf.format(DateUtils.getDayBegin()));
    statisticalVO.setToDayQuantity(toDayQuantity);

    //本周
    Long weekQuantity = this.baseMapper.getStatistical(warehouseId, sdf.format(DateUtils.getBeginDayOfWeek()));
    statisticalVO.setWeekQuantity(weekQuantity);

    //本月
    Long monthQuantity = this.baseMapper.getStatistical(warehouseId, sdf.format(DateUtils.getBeginDayOfMonth()));
    statisticalVO.setMonthQuantity(monthQuantity);

    return statisticalVO;
  }


  @Override
  public OrderDetailVO getOrderDetails(Long orderId) {
    JwtUser currentUser = SecurityUtils.getCurrentUser();
    Long warehouseId = currentUser.getWarehouseId();
    Preconditions.checkNotNull(warehouseId, "仓库ID不能为null");
    OrderDetailVO orderVO = this.baseMapper.getByIdAndWarehouseId(orderId, warehouseId);

    OrderUserVO orderUserVO = this.orderUserMapper.getOrderIdAndType(orderId, OrderUser.ORDER_TYPE_SHOPPING);
    orderVO.setOrderUser(orderUserVO);

    List<OrderItemVO> orderItemVO = this.orderItemMapper.getByOrderId(orderId);
    orderItemVO.forEach(itemVO -> itemVO.setTotalPrice(itemVO.getSalePrice() * itemVO.getQuantity()));
    orderVO.setOrderItems(orderItemVO);

    List<String> prescription = this.orderUserMapper.getPrescriptionByOrderId(orderId);
    List<String> prescriptionUrl = prescription.stream().map(s -> this.imgDomain + s).collect(Collectors.toList());
    orderVO.setPrescriptionUrl(prescriptionUrl);

    return orderVO;
  }

  @Override
  public List<LogisticsCompanyVO> logisticsCompanyList() {
    return this.baseMapper.getLogisticsCompanyList();
  }

  @Override
  public void deliveryFile(MultipartFile file) throws BusinessException {
    List<DeliveryExcelVO> inventoryExcels;
    try {
      ImportParams params = new ImportParams();
      params.setNeedVerfiy(true);
      inventoryExcels = ExcelImportUtil.importExcel(file.getInputStream(), DeliveryExcelVO.class, params);
    } catch (Exception e) {
      throw new BusinessException(BaseExceptionCodes.FAILED, "Excel发货失败", e);
    }

    Map<String, Long> logisticsMap = this.logisticsCompanyList()
        .stream()
        .collect(Collectors.toMap(LogisticsCompanyVO::getCode, LogisticsCompanyVO::getId));

    Set<OrderDeliveryBO> deliveryInfo = inventoryExcels.stream()
        .map(deliveryExcelVO -> {
          OrderDeliveryBO delivery = new OrderDeliveryBO();
          String orderSn = deliveryExcelVO.getOrderSn();
          Long orderId = this.baseMapper.getByOrderSn(orderSn);
          delivery.setOrderId(orderId);
          String expressCode = deliveryExcelVO.getExpressCode();
          delivery.setExpressId(logisticsMap.get(expressCode));
          delivery.setDeliveryId(deliveryExcelVO.getDeliveryId());
          return delivery;
        }).collect(Collectors.toSet());

    JwtUser currentUser = SecurityUtils.getCurrentUser();
    Long warehouseId = currentUser.getWarehouseId();
    Preconditions.checkNotNull(warehouseId, "仓库ID不能为null");
    this.orderFeignClient.delivery(warehouseId, deliveryInfo);

  }

  @Override
  public byte[] exportOrder(PageParamsVO pageParamsVO, OrderVO order) throws IOException {

    JwtUser currentUser = SecurityUtils.getCurrentUser();
    Long warehouseId = currentUser.getWarehouseId();

    QueryWrapper<?> entityWrapper = pageParamsVO.getEntityWrapper("t");
    entityWrapper.eq("oe.warehouse_id", warehouseId);

    String orderSn = order.getOrderSn();
    if (StringUtils.isNotBlank(orderSn)) {
      entityWrapper.in("oe.order_sn", orderSn.split("\n"));
    }
    String phone = order.getPhone();
    entityWrapper.eq(StringUtils.isNotBlank(phone), "eou.phone", phone);

    String receiver = order.getReceiver();
    entityWrapper.eq(StringUtils.isNotBlank(receiver), "eou.receiver", receiver);

    //发货日期
    String sendTimeGte = order.getSendTimeGte();
    String sendTimeLte = order.getSendTimeLte();
    entityWrapper.ge(StringUtils.isNotBlank(sendTimeGte), "oe.send_time", sendTimeGte);
    if (StringUtils.isNotBlank(sendTimeLte)) {
      if (DateUtils.isNow(sendTimeLte)) {
        Date plus = DateUtils.plus(DateUtils.parseStrToDate(sendTimeLte), 1, ChronoUnit.DAYS);
        entityWrapper.le("oe.send_time", plus);
      } else {
        entityWrapper.le("oe.send_time", sendTimeLte);
      }
    }

    Preconditions.checkNotNull(warehouseId, "仓库ID不能为null");
    entityWrapper.eq("oe.warehouse_id", warehouseId);

    Integer orderStatus = order.getOrderStatus();
    entityWrapper.eq(orderStatus != null, "oe.order_status", orderStatus);

    //商品sku码
    String skuNumber = order.getSkuNumber();
    entityWrapper.eq(StringUtils.isNotBlank(skuNumber), "ps.number", skuNumber);

    //商品名称
    String skuName = order.getSkuName();
    entityWrapper.like(StringUtils.isNotBlank(skuName), "ps.name", skuName);

    List<OrderExcelVO> list = this.baseMapper.exportOrder(entityWrapper);
    for (OrderExcelVO orderExcelVO : list) {
      orderExcelVO.setSalePrice(orderExcelVO.getSalePrice() / 100);
      orderExcelVO.setSkuPrice(orderExcelVO.getSkuPrice() / 100);
      orderExcelVO.setTotalMoney(orderExcelVO.getTotalMoney() / 100);
      orderExcelVO.setRealityMoney(orderExcelVO.getRealityMoney() / 100);
    }
    ExportParams exportParams = new ExportParams();
    Workbook workbook = ExcelExportUtil.exportExcel(exportParams, OrderExcelVO.class, list);
    ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
    workbook.write(byteArrayOutputStream);
    return byteArrayOutputStream.toByteArray();
  }

  @Override
  public PrintOrderDetailVO printOrder(Long orderId) {

    PrintOrderDetailVO printOrderDetailVO = this.baseMapper.getPrintOrderDetailById(orderId);
    String orderSn = printOrderDetailVO.getOrderSn();
    BufferedImage bufferedImage = BarCodeUtil.encode(orderSn);
    ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
    try {
      ImageIO.write(bufferedImage, "jpg", outputStream);
      byte[] encode = Base64.getEncoder().encode(outputStream.toByteArray());
      printOrderDetailVO.setOrderSnBarcode("data:image/png;base64," + new String(encode));
    } catch (IOException e) {
      this.log.error("条形码转换失败", e);
    }

    List<OrderItemVO> orderItemVO = this.orderItemMapper.getByOrderId(orderId);
    orderItemVO.forEach(itemVO -> itemVO.setTotalPrice(itemVO.getSalePrice() * itemVO.getQuantity()));
    printOrderDetailVO.setOrderItems(orderItemVO);
    return printOrderDetailVO;
  }

  @Override
  public Boolean tip() {
    // 这里查询五分钟内的订单，
    Date date = DateUtils.plus(new Date(), 5, ChronoUnit.MINUTES);
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    JwtUser currentUser = SecurityUtils.getCurrentUser();
    Long warehouseId = currentUser.getWarehouseId();
    Long countOrder = this.baseMapper.countOrder(warehouseId, sdf.format(date));
    return countOrder != null && countOrder != 0;
  }

}
